#ifndef __PADDLEOCR_OPENVINO_H
#define __PADDLEOCR_OPENVINO_H

#include <cstdio>
#include <string>

#include <cstdlib>
#include <fstream>
#include <iostream>
#include <sstream>
#include <ctime>
 
#include <iterator>
#include <memory>
#include <sstream>
#include <vector>

#include <openvino/openvino.hpp>

#include "opencv2/opencv.hpp"
#include "opencv2/core/core.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"

#include "EDLines.h"

#include <unistd.h>
#include <sys/time.h>

typedef struct
{
    int x0;
    int y0;
    int x1;
    int y1;
    double angle;
}MLine;

class PaddleOcrOpenvino {
public:

    PaddleOcrOpenvino();
    virtual ~PaddleOcrOpenvino();

    bool Init(char *weight, char *dictFile);

    bool Ocr2rd(cv::Mat &img, cv::Rect &rect, std::string &result, int &iscore);
    bool Ocr2rd(cv::Mat &img, cv::Rect &rect, std::string &result, int &iscore, int &lastScore);

    bool Ocr(cv::Mat &img, cv::Rect &rect, std::string &result, int &iscore, int &lastScore);
    bool Ocr(cv::Mat &img, cv::Rect &rect, std::string &result, int &iscore);
    bool Ocr(cv::Mat &img, std::string &result, int &iscore);

    bool OcrPaddleProcess(cv::Mat &img, std::string &result, int &iscore);
    bool OcrPaddleProcess(cv::Mat &img, std::string &result, int &iscore, int &lastScore);

    bool IsInitOK(){return isInitOk;};

    void AdjectRect(cv::Mat &oriMat, cv::Rect &rect, int x0, int y0, int w0, int h0);
    bool OcrEDLine(cv::Mat &img, cv::Mat &procImg, cv::Rect &box, std::string &result, int &iscore);
    bool OcrEDLine(cv::Mat &img, cv::Mat &procImg, cv::Rect &box, std::string &result, int &iscore, int &lastScore);

private:

    ov::Core core;
    std::shared_ptr<ov::Model> model;
    ov::CompiledModel compiled_model;
    ov::InferRequest infer_request;
    ov::Tensor input_tensor;
    ov::Shape tensor_shape;

    float mean[3] = {0.485, 0.456, 0.406};
    float std[3] = {0.229, 0.224, 0.225};

    int inChannel;
    int inWidth;
    int inHeight;

    std::vector<std::string> dict;

    bool isInitOk = false;

    bool InitDict(char *file, std::vector<std::string> &dict);

    void paddleResize(cv::Mat &img, cv::Mat &resize_img);
    void normalize(cv::Mat *im, float *mean,
            float *scale, bool is_scale);

    bool parkidProcess(cv::Mat &oriMat, cv::Mat &retMat, cv::Rect &box);
    void edlinesProc(cv::Mat &imageParkid, MLine &line1, MLine &line2);

    double Hudu2Jiaodu(double hudu);
};

#endif
